package ar.com.algotres.tpdos.model.aviones;

import java.util.Queue;

import ar.com.algotres.tpdos.estrategia.aterrizaje.EstrategiaAterrizaje;
import ar.com.algotres.tpdos.model.aterrizable.Pista;
import ar.com.algotres.tpdos.model.controlador.TorreDeControl;
import ar.com.algotres.tpdos.model.fisica.Movimiento;
import ar.com.algotres.tpdos.model.fisica.Posicion;
import ar.com.algotres.tpdos.model.fisica.Trayectoria;

public abstract class Avion {

	private CaracteristicasAvion caracteristicas;
	private Movimiento movimiento;
	private Posicion posicion;
	private EstrategiaAterrizaje estrategiaAterrizaje;
	private TorreDeControl torreDeControl;
	private EstadoAvion estado;
	private Queue<Trayectoria> trayectorias;

	
	public Avion(TorreDeControl torre, Movimiento movimiento,
			EstrategiaAterrizaje estrategiaAterrizaje, Posicion posicion,
			CaracteristicasAvion caracteristicas) {
		this.movimiento = movimiento;
		this.estrategiaAterrizaje = estrategiaAterrizaje;
		this.torreDeControl = torre;
		this.posicion = posicion;
		this.estado = EstadoAvion.VOLANDO;
		this.caracteristicas = caracteristicas;
	}

	public void mover() {
		
		Posicion posicionActual = this.posicion; 
		
		if (posicionActual.equals(movimiento.getTrayectoria().getPosicionFinal())
				&& trayectorias != null && !trayectorias.isEmpty()){
			Trayectoria trayectoria = this.trayectorias.poll();
			this.movimiento = new Movimiento(this.movimiento.getVelocidad(), trayectoria);
		}
		
		int nuevaPosX =  posicionActual.getX() + (int) this.movimiento.getDesplazamientoEnX();
		int nuevaPosY =  posicionActual.getY() + (int) this.movimiento.getDesplazamientoEnY();
		
		nuevaPosX = this.getDesplazamientoCorrectoEnX(movimiento.getTrayectoria().getPosicionFinal(), nuevaPosX);
		nuevaPosY = this.getDesplazamientoCorrectoEnY(movimiento.getTrayectoria().getPosicionFinal(), nuevaPosY);
		
		this.posicion = new Posicion(nuevaPosX, nuevaPosY);
		
	}
	
	private int getDesplazamientoCorrectoEnX(Posicion posicionFinal,int desplazamientoX){
		return this.esDesplazamientoCorrectoX(posicionFinal, desplazamientoX) ? desplazamientoX : posicionFinal.getX();
	}

	private int getDesplazamientoCorrectoEnY(Posicion posicionFinal,int desplazamientoY){
		return this.esDesplazamientoCorrectoY(posicionFinal, desplazamientoY) ? desplazamientoY : posicionFinal.getY();
	}

	private Boolean esDesplazamientoCorrectoX(Posicion posicionFinal, int desplazamientoX ){
		Double deltaMovimiento = Math.abs(movimiento.getDesplazamientoEnX());
		Double deltaX = Math.abs((double) (posicionFinal.getX() - posicion.getX()));
		return deltaMovimiento < deltaX; 
	}
	
	private Boolean esDesplazamientoCorrectoY(Posicion posicionFinal, int desplazamientoY){
		Double deltaMovimiento = Math.abs(movimiento.getDesplazamientoEnY());
		Double deltaY = Math.abs((double) (posicionFinal.getY() - posicion.getY()));
		return deltaMovimiento < deltaY; 
	}

	public Queue<Trayectoria> getTrayectorias() {
		return trayectorias;
	}

	public void setTrayectorias(Queue<Trayectoria> trayectorias) {
		this.trayectorias = trayectorias;
	}

	public EstrategiaAterrizaje getEstrategiaAterrizaje() {
		return estrategiaAterrizaje;
	}

	public void setEstrategiaAterrizaje(
			EstrategiaAterrizaje estrategiaAterrizaje) {
		this.estrategiaAterrizaje = estrategiaAterrizaje;
	}

	public Movimiento getMovimiento() {
		return movimiento;
	}

	public void setMovimiento(Movimiento movimiento) {
		this.movimiento = movimiento;
	}

	public Posicion getPosicion() {
		return posicion;
	}

	public void setPosicion(Posicion posicion) {
		this.posicion = posicion;
	}

	public TorreDeControl getTorreDeControl() {
		return torreDeControl;
	}

	public EstadoAvion getEstado() {
		return estado;
	}

	public CaracteristicasAvion getCaracteristicas() {
		return caracteristicas;
	}
	
	@Override
	public String toString(){
		return "Estado: " + estado.name() + " | Posición: X = "+ posicion.getX() + " ; Y = " + posicion.getY();
	}
	
	public boolean tienePistaValida(){
		return torreDeControl.tienePistaValida(this);
	}
	
	public abstract boolean puedeAterrizarEnPista(Pista pista);
	
	public void aterrizar(){
		estado = EstadoAvion.ATERRIZADO;
	}

}
